package de.farbstreich.tozen2.common;

import java.util.HashMap;
import java.util.Map;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import de.farbstreich.tozen2.common.TozenProtocolMessage.player;
import de.farbstreich.tozen2.common.TozenProtocolMessage.position;
/**
 * This class holds all methods used for encoding the 
 * information of a TozenProtocolMessage into the JSON Format.
 * 
 * @author Tim Babies
 *
 */

public class TozenProtocolEncoder {
	private TozenProtocolMessage t;
	private JSONObject obj;
	/**	
	 * This is the standard constructor for this class
	 * @param t
	 * @param obj
	 * 
	 */
	public TozenProtocolEncoder(TozenProtocolMessage t, JSONObject obj){
		this.t = t;
		this.obj = obj;
				
	}
	/**
	 * This Method scans the input and forwards it to the correct
	 * encoding Method.
	 * @return
	 */
	public JSONObject encode(){
		//System.out.println("Encoding...");
		
		switch (t.type) {
		case SET_NAME:
			encodeSetName(obj);
			break;
		case LOGOUT:
			encodeLogout(obj);
			break;
		case GAMES:
			encodeGames(obj);
			break;
		case GAME_TYPES:
			encodeGameTypes(obj);
			break;
		case SET_GAME:
			encodeSetGame(obj);
			break;
		case PLAYERS:
			encodePlayers(obj);
			break;
		case START_GAME:
			encodeStartGame(obj);
			break;
		case GAME:
			encodeGame(obj);
			break;
		case POSITIONS:
			encodePositions(obj);
			break;
		case CURRENT_PLAYER:
			encodeCurrentPlayer(obj);
			break;
		case TEST_MOVE:
			encodeTestMove(obj);
			break;
		case SURRENDER_GAME:
			encodeSurrenderGame(obj);
			break;
		case END_GAME:
			encodeEndGame(obj);
			break;
		case MESSAGE:
			encodeMessage(obj);
			break;
		case PING:
			encodePing(obj);
			break;
		case JOIN_GAME:
			encodeJoinGame(obj);
			break;

		}
		
		
		return obj;
		
		
		
	}
	/**
	 * Encodes a message with the TozenMessageType JOIN_GAME
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */

	private JSONObject encodeJoinGame(JSONObject obj1){
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		obj1.put("gameId", t.games[0].id);
		return obj1;
	}
	
	/**
	 * Encodes a message with the TozenMessageType SET_NAME
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */

	private JSONObject encodeSetName(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		obj1.put("playerName", t.players.get(0).name);
		obj1.put("playerId", t.players.get(0).id);
		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType LOGOUT
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */

	private JSONObject encodeLogout(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType GAMES
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	private JSONObject encodeGames(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		obj1.put("games", t.games.length);

		JSONArray list = new JSONArray();

		for (int i = 0; i < t.games.length; i++) {
			Map m = new HashMap();
			m.put("gameId", t.games[i].id);
			m.put("gameTitle", t.games[i].title);
			m.put("gameName", t.games[i].name);
			m.put("maxPlayersCount", t.games[i].maxPlayersCount);
			m.put("playersCount", t.games[i].playersCount);
			//m.put("options", games[i].options);
			list.add(m);
		}
		obj1.put("gamesList", list);
		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType GAME_TYPES
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */

	private JSONObject encodeGameTypes(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		obj1.put("gameTypes", t.gameTypes.length);
		JSONArray list = new JSONArray();
		for (int i = 0; i < t.gameTypes.length; i++) {
			JSONObject obj2 = new JSONObject();
			obj2.put("typeId", t.gameTypes[i].id);
			obj2.put("gameTitle", t.gameTypes[i].title);
			obj2.put("maxPlayersCount", t.gameTypes[i].maxPlayersCount);
			obj2.put("minPlayersCount", t.gameTypes[i].minPlayersCount);
			//JSONObject obj3 = (JSONObject) gameTypes[i].options;
			//obj2.put("options", obj3);
			list.add(obj2);
		}
		obj1.put("gameTypesList", list);
		return obj1;
	}
	
	/**
	 * Encodes a message with the TozenMessageType SET_GAME
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	private JSONObject encodeSetGame(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		JSONArray list = new JSONArray();
		list.add(t.games[0].id);
		list.add(t.games[0].name);
		obj1.put("setGame", list);
		//JSONObject obj2 = (JSONObject) games[0].options;
		//obj1.put("options", obj2);

		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType PLAYERS
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	private JSONObject encodePlayers(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		JSONArray list = new JSONArray();

		for (player p : t.players) {
			JSONObject obj2 = new JSONObject();

			obj2.put("playerId", p.id);
			obj2.put("playerName", p.name);
			obj2.put("ingame", p.ingame);
			list.add(obj2);
		}
		obj1.put("playersList", list);

		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType START_GAME
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	private JSONObject encodeStartGame(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType GAME
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */

	private JSONObject encodeGame(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		obj1.put("gameId", t.games[0].id);
		obj1.put("gameTitle", t.games[0].title);
		obj1.put("gameName", t.games[0].name);
		obj1.put("minPlayersCount", t.games[0].minPlayersCount);
		
		JSONArray playersList = new JSONArray();
		for (player p: t.games[0].players) {
			JSONObject obj2 = new JSONObject();
			obj2.put("id", p.id);
			obj2.put("name", p.name);
			obj2.put("color", p.color);
			playersList.add(obj2);
		}
		obj1.put("playersList", playersList);
	
		JSONArray positionList = new JSONArray();
		for(position p : t.games[0].positions) {
			JSONObject jp = new JSONObject();
			jp.put("x", p.x);
			jp.put("y", p.y);
			jp.put("playerId", p.playerId);
			jp.put("tileId", p.tileId);
			positionList.add(jp);
		}
		obj1.put("positionsList", positionList);

		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType POSITIONS
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	// positions: [ {x (int), y (int), tileType (int), playerId (int)}, ... ]
	private JSONObject encodePositions(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		
		JSONArray positionList = new JSONArray();
		for(position p : t.games[0].positions) {
			JSONObject jp = new JSONObject();
			jp.put("x", p.x);
			jp.put("y", p.y);
			jp.put("playerId", p.playerId);
			jp.put("tileId", p.tileId);
			positionList.add(jp);
		}
		obj1.put("positionsList", positionList);
		return obj1;
		
		
	}
	/**
	 * Encodes a message with the TozenMessageType CURRENT_PLAYER
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	private JSONObject encodeCurrentPlayer(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		obj1.put("currentPlayer", t.players.get(0).id);
		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType TEST_MOVE
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	private JSONObject encodeTestMove(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		obj1.put("startX", t.startX);
		obj1.put("startY", t.startY);
		obj1.put("targetX", t.targetX);
		obj1.put("targetY", t.targetY);
		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType SURRENDER_GAME
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	private JSONObject encodeSurrenderGame(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		
		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType END_GAME
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	private JSONObject encodeEndGame(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType MESSAGE
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	private JSONObject encodeMessage(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		JSONArray list = new JSONArray();
		list.add(t.players.get(0).id);
		list.add(t.message);
		list.add(t.broadcast);
		obj1.put("messageoptions", list);
		return obj1;
	}
	/**
	 * Encodes a message with the TozenMessageType PING
	 * 
	 * @param obj1 JSONOBJECT
	 * @return
	 */
	private JSONObject encodePing(JSONObject obj1) {
		obj1.put("type", t.type.toString());
		obj1.put("status", t.status);
		return obj1;
	}

}
